#!/usr/bin/env python

'''Main

@author Julot <andy.julot@gmail.com>
@since Wednesday, January 18, 2012. 11:04 AM'''

import app
import sys
import model
import random
import logging
import miniboa
import colorama
import datetime

import resource as r

from autorm.db.connection import autorm_db, Database

success = lambda x: sys.stdout.write(colorama.Fore.GREEN +
                                     colorama.Style.BRIGHT + x)
progress = lambda x: sys.stdout.write(colorama.Fore.CYAN +
                                      colorama.Style.BRIGHT + x)
warning = lambda x: sys.stdout.write(colorama.Fore.YELLOW +
                                     colorama.Style.BRIGHT + x)
fail = lambda x: sys.stdout.write(colorama.Fore.RED +
                                  colorama.Style.BRIGHT + x)
info = lambda x: sys.stdout.write(colorama.Fore.WHITE +
                                  colorama.Style.BRIGHT + x)
confirm = lambda x: raw_input(colorama.Fore.WHITE + colorama.Style.BRIGHT + 
                              '%s [yes|no] ' % x)[0].lower() == 'y'

class App(app.App):
    '''App class
    
    @author Julot <andy.julot@gmail.com>
    @since Sunday, January 15, 2012. 05:42 PM'''
    
    _clients = []
    
    def run(self):
        self.initTable()
        connect = self.onConnect
        dc = self.onDisconnect
        server = miniboa.TelnetServer(6667, '', connect, dc, 0.005)
        while True:
            server.poll()
            self.process()
    
    def process(self):
        for client in self._clients:
            if client.active and client.cmd_ready:
                self.attention(client)
    
    def attention(self, client):
        command = client.get_command().strip()
        if not command: return
        
        self.now()
        info('<< \'%s\' from %s\n' % (command, client.addrport()))
        
        commands = command.split(' ')
        
        cmd = commands[0].lower()
        if cmd == 'ats':
            value = self.loadValue(command)
            client.send('%s\n' % value)
            print '>> %s to %s' % (value, client.addrport())
            client.send('%s\n' % value)
        elif cmd == 'atk':
            self.saveValue(command)
            info('!! Value saved to database')
    
    def castInt(self, value):
        try: return int(value)
        except: return None
    
    def loadValue(self, command):
        self.openDb()
        devices = model.Device.objects.query()
        r = []
        for device in devices:
            #t = (device.host, device.channel, device.value)
            t = (device.host, device.channel, random.randint(0, 100))
            r.append('%02d%02d%03d' % t)
        self.closeDb()
        return ','.join(r)
    
    def saveValue(self, command):
        value = self.castInt(command[8:])
        if value is None: return
        
        self.openDb()
        host = self.castInt(command[4:6])
        channel = self.castInt(command[6:8])
        if host and channel:
            # If host and channel defined, create a new record if not exist
            device = model.Device.objects.query(host=host, channel=channel)[0]
            if not device:
                device = model.Device(host=host, channel=channel)
            device.value = value
            device.save()
        elif host:
            # Because we will never know the channel, don't create a new record.
            # Just save the already existing channel.
            devices = model.Device.objects.query(host=host)
            for device in devices:
                device.value = value
                device.save()
        self.closeDb()
    
    def now(self):
        info(datetime.datetime.now().strftime(':: %Y-%m-%d %H:%M:%S\n'))
    
    def initTable(self):
        autorm_db.conn.connect('sqlite3', '%s.db' % r.string.app.name)
        tables = (model.Device,)
        for table in tables:
            table.createTable()
            table.createIndex()
    
    def openDb(self):
        autorm_db.conn.connect('sqlite3', '%s.db' % r.string.app.name)
    
    def closeDb(self):
        autorm_db.conn = Database()
    
    def onConnect(self, client):
        '''Default method to handle new connection
        
        @param object client object'''
        
        client.request_wont_echo()
        self._clients.append(client)
        self.now()
        info('++ Connection to %s opened.\n' % client.addrport())
        
    def onDisconnect(self, client):
        '''Default method to handle lost connection
        
        @param object client object'''
        
        self._clients.remove(client)
        self.now()
        info('-- Connection to %s closed.\n' % client.addrport())
    
if __name__ == '__main__':
    console = App()
    console.run()
    # Make sure that destructor in App is called
    del console